package com.gitee.wsl.time.chinese.util

import com.gitee.wsl.ext.base.currentDateTime
import com.gitee.wsl.text.format.format
import com.gitee.wsl.time.T
import com.gitee.wsl.time.YearMonth
import com.gitee.wsl.time.chinese.util.LunarUtil.find
import com.gitee.wsl.time.chinese.util.LunarUtil.getJiaZiIndex
import com.gitee.wsl.time.weeksInMonth
import kotlinx.datetime.DayOfWeek
import kotlinx.datetime.LocalDateTime
import kotlin.math.round
import kotlin.time.ExperimentalTime


/**
 * 阳历工具
 *
 * @author 6tail
 */
object SolarUtil {
    /**
     * 星期
     */
    val WEEK: Array<String> = arrayOf<String>("日", "一", "二", "三", "四", "五", "六")

    /**
     * 每月天数
     */
    val DAYS_OF_MONTH: IntArray = intArrayOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

    /**
     * 星座
     */
    val XINGZUO: Array<String> =
        arrayOf<String>("白羊", "金牛", "双子", "巨蟹", "狮子", "处女", "天秤", "天蝎", "射手", "摩羯", "水瓶", "双鱼")

    /**
     * 日期对应的节日
     */
    val FESTIVAL: Map<String, String> = mutableMapOf<String, String>().apply{
            put("1-1", "元旦节")
            put("2-14", "情人节")
            put("3-8", "妇女节")
            put("3-12", "植树节")
            put("3-15", "消费者权益日")
            put("4-1", "愚人节")
            put("5-1", "劳动节")
            put("5-4", "青年节")
            put("6-1", "儿童节")
            put("7-1", "建党节")
            put("8-1", "建军节")
            put("9-10", "教师节")
            put("10-1", "国庆节")
            put("10-31", "万圣节前夜")
            put("11-1", "万圣节")
            put("12-24", "平安夜")
            put("12-25", "圣诞节")
    }

    /**
     * 几月第几个星期几对应的节日
     */
    val WEEK_FESTIVAL: Map<String, String> = mutableMapOf<String, String>().apply{
            put("3-0-1", "全国中小学生安全教育日")
            put("5-2-0", "母亲节")
            put("6-3-0", "父亲节")
            put("11-4-4", "感恩节")
    }

    /**
     * 日期对应的非正式节日
     */
    val OTHER_FESTIVAL: Map<String, List<String>> = mutableMapOf<String, List<String>>().apply{
            put("1-8", listOf( "周恩来逝世纪念日"))
            put("1-10", listOf( "中国人民警察节"))
            put("1-14", listOf( "日记情人节"))
            put("1-21", listOf( "列宁逝世纪念日"))
            put("1-26", listOf( "国际海关日"))
            put("1-27", listOf( "国际大屠杀纪念日"))
            put("2-2", listOf( "世界湿地日"))
            put("2-4", listOf( "世界抗癌日"))
            put("2-7", listOf( "京汉铁路罢工纪念日"))
            put("2-10", listOf( "国际气象节"))
            put("2-19", listOf( "邓小平逝世纪念日"))
            put("2-20", listOf( "世界社会公正日"))
            put("2-21", listOf( "国际母语日"))
            put("2-24", listOf( "第三世界青年日"))
            put("3-1", listOf( "国际海豹日"))
            put("3-3", listOf("世界野生动植物日", "全国爱耳日"))
            put("3-5", listOf("周恩来诞辰纪念日", "中国青年志愿者服务日"))
            put("3-6", listOf( "世界青光眼日"))
            put("3-7", listOf( "女生节"))
            put("3-12", listOf( "孙中山逝世纪念日"))
            put("3-14", listOf("马克思逝世纪念日", "白色情人节"))
            put("3-17", listOf( "国际航海日"))
            put("3-18", listOf("全国科技人才活动日", "全国爱肝日"))
            put("3-20", listOf( "国际幸福日"))
            put("3-21", listOf("世界森林日", "世界睡眠日", "国际消除种族歧视日"))
            put("3-22", listOf( "世界水日"))
            put("3-23", listOf( "世界气象日"))
            put("3-24", listOf( "世界防治结核病日"))
            put("3-29", listOf( "中国黄花岗七十二烈士殉难纪念日"))
            put("4-2", listOf("国际儿童图书日", "世界自闭症日"))
            put("4-4", listOf( "国际地雷行动日"))
            put("4-7", listOf( "世界卫生日"))
            put("4-8", listOf( "国际珍稀动物保护日"))
            put("4-12", listOf( "世界航天日"))
            put("4-14", listOf( "黑色情人节"))
            put("4-15", listOf( "全民国家安全教育日"))
            put("4-22", listOf("世界地球日", "列宁诞辰纪念日"))
            put("4-23", listOf( "世界读书日"))
            put("4-24", listOf( "中国航天日"))
            put("4-25", listOf( "儿童预防接种宣传日"))
            put("4-26", listOf("世界知识产权日", "全国疟疾日"))
            put("4-28", listOf( "世界安全生产与健康日"))
            put("4-30", listOf( "全国交通安全反思日"))
            put("5-2", listOf( "世界金枪鱼日"))
            put("5-3", listOf( "世界新闻自由日"))
            put("5-5", listOf( "马克思诞辰纪念日"))
            put("5-8", listOf( "世界红十字日"))
            put("5-11", listOf( "世界肥胖日"))
            put("5-12", listOf("全国防灾减灾日", "护士节"))
            put("5-14", listOf( "玫瑰情人节"))
            put("5-15", listOf( "国际家庭日"))
            put("5-19", listOf( "中国旅游日"))
            put("5-20", listOf( "网络情人节"))
            put("5-22", listOf( "国际生物多样性日"))
            put("5-25", listOf( "525心理健康节"))
            put("5-27", listOf( "上海解放日"))
            put("5-29", listOf( "国际维和人员日"))
            put("5-30", listOf( "中国五卅运动纪念日"))
            put("5-31", listOf( "世界无烟日"))
            put("6-3", listOf( "世界自行车日"))
            put("6-5", listOf( "世界环境日"))
            put("6-6", listOf( "全国爱眼日"))
            put("6-8", listOf( "世界海洋日"))
            put("6-11", listOf( "中国人口日"))
            put("6-14", listOf("世界献血日", "亲亲情人节"))
            put("6-17", listOf( "世界防治荒漠化与干旱日"))
            put("6-20", listOf( "世界难民日"))
            put("6-21", listOf( "国际瑜伽日"))
            put("6-25", listOf( "全国土地日"))
            put("6-26", listOf("国际禁毒日", "联合国宪章日"))
            put("7-1", listOf( "香港回归纪念日"))
            put("7-6", listOf("国际接吻日", "朱德逝世纪念日"))
            put("7-7", listOf( "七七事变纪念日"))
            put("7-11", listOf("世界人口日", "中国航海日"))
            put("7-14", listOf( "银色情人节"))
            put("7-18", listOf( "曼德拉国际日"))
            put("7-30", listOf( "国际友谊日"))
            put("8-3", listOf( "男人节"))
            put("8-5", listOf( "恩格斯逝世纪念日"))
            put("8-6", listOf( "国际电影节"))
            put("8-8", listOf( "全民健身日"))
            put("8-9", listOf( "国际土著人日"))
            put("8-12", listOf( "国际青年节"))
            put("8-14", listOf( "绿色情人节"))
            put("8-19", listOf("世界人道主义日", "中国医师节"))
            put("8-22", listOf( "邓小平诞辰纪念日"))
            put("8-29", listOf( "全国测绘法宣传日"))
            put("9-3", listOf( "中国抗日战争胜利纪念日"))
            put("9-5", listOf( "中华慈善日"))
            put("9-8", listOf( "世界扫盲日"))
            put("9-9", listOf("毛泽东逝世纪念日", "全国拒绝酒驾日"))
            put("9-14", listOf("世界清洁地球日", "相片情人节"))
            put("9-15", listOf( "国际民主日"))
            put("9-16", listOf( "国际臭氧层保护日"))
            put("9-17", listOf( "世界骑行日"))
            put("9-18", listOf( "九一八事变纪念日"))
            put("9-20", listOf( "全国爱牙日"))
            put("9-21", listOf( "国际和平日"))
            put("9-27", listOf( "世界旅游日"))
            put("9-30", listOf( "中国烈士纪念日"))
            put("10-1", listOf( "国际老年人日"))
            put("10-2", listOf( "国际非暴力日"))
            put("10-4", listOf( "世界动物日"))
            put("10-11", listOf( "国际女童日"))
            put("10-10", listOf( "辛亥革命纪念日"))
            put("10-13", listOf("国际减轻自然灾害日", "中国少年先锋队诞辰日"))
            put("10-14", listOf( "葡萄酒情人节"))
            put("10-16", listOf( "世界粮食日"))
            put("10-17", listOf( "全国扶贫日"))
            put("10-20", listOf( "世界统计日"))
            put("10-24", listOf("世界发展信息日", "程序员节"))
            put("10-25", listOf( "抗美援朝纪念日"))
            put("11-5", listOf( "世界海啸日"))
            put("11-8", listOf( "记者节"))
            put("11-9", listOf( "全国消防日"))
            put("11-11", listOf( "光棍节"))
            put("11-12", listOf( "孙中山诞辰纪念日"))
            put("11-14", listOf( "电影情人节"))
            put("11-16", listOf( "国际宽容日"))
            put("11-17", listOf( "国际大学生节"))
            put("11-19", listOf( "世界厕所日"))
            put("11-28", listOf( "恩格斯诞辰纪念日"))
            put("11-29", listOf( "国际声援巴勒斯坦人民日"))
            put("12-1", listOf( "世界艾滋病日"))
            put("12-2", listOf( "全国交通安全日"))
            put("12-3", listOf( "世界残疾人日"))
            put("12-4", listOf( "全国法制宣传日"))
            put("12-5", listOf("世界弱能人士日", "国际志愿人员日"))
            put("12-7", listOf( "国际民航日"))
            put("12-9", listOf("世界足球日", "国际反腐败日"))
            put("12-10", listOf( "世界人权日"))
            put("12-11", listOf( "国际山岳日"))
            put("12-12", listOf( "西安事变纪念日"))
            put("12-13", listOf( "国家公祭日"))
            put("12-14", listOf( "拥抱情人节"))
            put("12-18", listOf( "国际移徙者日"))
            put("12-26", listOf( "毛泽东诞辰纪念日"))
    }

    /**
     * 是否闰年
     *
     * @param year 年
     * @return true/false 闰年/非闰年
     */
    fun isLeapYear(year: Int): Boolean {
        if (year < 1600) {
            return year % 4 == 0
        }
        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
    }

    /**
     * 获取某年有多少天（平年365天，闰年366天）
     *
     * @param year 年
     * @return 天数
     */
    fun getDaysOfYear(year: Int): Int {
        if (1582 == year) {
            return 355
        }
        return if (isLeapYear(year)) 366 else 365
    }

    /**
     * 获取某年某月有多少天
     *
     * @param year  年
     * @param month 月
     * @return 天数
     */
    fun getDaysOfMonth(year: Int, month: Int): Int {
        if (1582 == year && 10 == month) {
            return 21
        }
        val m = month - 1
        var d = DAYS_OF_MONTH[m]
        //公历闰年2月多一天
        if (month == 2 && isLeapYear(year)) {
            d++
        }
        return d
    }

    /**
     * 获取某天为当年的第几天
     *
     * @param year 年
     * @param month 月
     * @param day 日
     * @return 第几天
     */
    fun getDaysInYear(year: Int, month: Int, day: Int): Int {
        var days = 0
        for (i in 1..<month) {
            days += getDaysOfMonth(year, i)
        }
        var d = day
        if (1582 == year && 10 == month) {
            if (day >= 15) {
                d -= 10
            } else require(day <= 4) { String.format("wrong solar year %d month %d day %d", year, month, day) }
        }
        days += d
        return days
    }

    /**
     * 获取某年某月有多少周
     *
     * @param year  年
     * @param month 月
     * @param start 星期几作为一周的开始，1234560分别代表星期一至星期天
     * @return 周数
     */
    @OptIn(ExperimentalTime::class)
    fun getWeeksOfMonth(year: Int, month: Int, start: Int = DayOfWeek.MONDAY.ordinal): Int {
        return YearMonth(year,month).weeksInMonth(DayOfWeek(start))
//        return ceil(
//            (getDaysOfMonth(year, month) + Solar.fromYmd(year, month, 1).getWeek() - start) * 1.0 / WEEK.size
//        ).toInt()
    }

    /**
     * 获取两个日期之间相差的天数（如果日期a比日期b小，天数为正，如果日期a比日期b大，天数为负）
     *
     * @param ay 年a
     * @param am 月a
     * @param ad 日a
     * @param by 年b
     * @param bm 月b
     * @param bd 日b
     * @return 天数
     */
    fun getDaysBetween(ay: Int, am: Int, ad: Int, by: Int, bm: Int, bd: Int): Int {
        val n: Int
        var days: Int
        var i: Int
        if (ay == by) {
            n = getDaysInYear(by, bm, bd) - getDaysInYear(ay, am, ad)
        } else if (ay > by) {
            days = getDaysOfYear(by) - getDaysInYear(by, bm, bd)
            i = by + 1
            while (i < ay) {
                days += getDaysOfYear(i)
                i++
            }
            days += getDaysInYear(ay, am, ad)
            n = -days
        } else {
            days = getDaysOfYear(ay) - getDaysInYear(ay, am, ad)
            i = ay + 1
            while (i < by) {
                days += getDaysOfYear(i)
                i++
            }
            days += getDaysInYear(by, bm, bd)
            n = days
        }
        return n
    }
}
